import gauge.DialGauge3State;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Image;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.border.BevelBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/*TODO
 *  
 *  4.) add a label like "speed" or "fuel" -- make it optional
 *  5.) add a digital readout -- also optional to show
 *  6.) make gauge work oriented left, right,top,bottom half-gauges
 *  7.) make the ui a propertyChangeListener of the model so I don't have to keep getting model parameters
 *      the UI can hold them and update them if they change in the model
 *  8.) add look and feel capabilities
 *  9.) rethink and set sane defaults for all parameters
 *  10.) Build your own background images (the ones stolen from the internet won't fully cut it in production
 *  11.) add a bezel around the gauge (optional)
 *  12.) add scaling capability
 *  13.) rethink positioning (eh?)
 *  14.) think about how to get it "out there" for feedback" (SourceForge?)
 *  15.) build a more complicated test panel to demonstrate the options
 *  	15.a) add checkboxes to set things like "show ticks"
 *  16.) move defaults to constants
 *  17.) add unit testing
 *  18.) add checkstyles and correct code to convention
 *  19.) javadoc and pretty up the code.
 *  20.) consider turning the SpinSlider panels into a widget
 *  21.) Make the model keep track of which state the gauge is in, ie
 *  		critical low, warn low, safe, warn high, critical high.  Make these
 *  		states cause propertyChange events.  The gui would take action such
 *  		as setting gauge background color based on reading the state.  The 
 *  		gauge or the gui might also fire additional events that could trigger
 *  		events, bells, etc.  The warning zones could then provide hysteresis for 
 *  		heaters, etc.
 */

public class GaugeTestPanel implements ChangeListener{
	JFrame frame;
	JPanel panel;
	DialGauge3State gauge;
	SpinSlider valueSlider;
	SpinSlider lctpSlider;
	SpinSlider stpSlider;
	SpinSlider uctpSlider;
	SpinSlider udtpSlider;
	SpinSlider zoneWidthSlider;
	SpinSlider minSlider;
	SpinSlider maxSlider;
	SpinSlider offsetSlider;
	SpinSlider degRangeSlider;
	SpinSlider majorTickSlider;
	SpinSlider minorTickSlider;
	
	
	
	
	public GaugeTestPanel() 
	{
		frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		panel = new JPanel();
		frame.add(panel);
		
		panel.setLayout(new FlowLayout());
		/*
		 * public DialGauge3State(double degreeOffset,double degreeRange,double min,double max,
			double majorTickSpacing,double minorTickSpacing,
			double cautionTripPoint,double dangerTripPoint)
			
		 */
		gauge = new DialGauge3State(225,270,0,180,10,2,70,75);
		gauge.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
		
		
		gauge.setScale(.5f);
		
		panel.add(gauge);
		
		//Gauge needs to set its own preferred size to something sane.
		//gauge.setPreferredSize(new Dimension(350,350));
		gauge.setLowerCautionTripPoint(55);
		gauge.setSafeTripPoint(60);
		gauge.setDrawMinorTickMarks(true);
		gauge.setDrawMajorTickMarks(true);
		gauge.setDrawLabels(true);
	//	gauge.setUpperCautionTripPoint(30);
	//	gauge.setUpperDangerTripPoint(40);
		gauge.setZoneArcThickness(1);
		
		lctpSlider = new SpinSlider("LCTP",0,(int)gauge.getMax(),(int)gauge.getLowerCautionTripPoint());
		stpSlider = new SpinSlider("STP",0,(int)gauge.getMax(),(int)gauge.getSafeTripPoint());
		uctpSlider = new SpinSlider("UCTP",0,(int)gauge.getMax(),(int)gauge.getUpperCautionTripPoint());
		udtpSlider = new SpinSlider("UDTP",0,(int)gauge.getMax(),(int)gauge.getUpperDangerTripPoint());
		zoneWidthSlider = new SpinSlider("ZONEWIDTH",0,180,(int)gauge.getZoneArcThickness());
		minSlider = new SpinSlider("MIN",0,360,(int)gauge.getMin());
		maxSlider = new SpinSlider("MAX",0,360,(int)gauge.getMax());
		offsetSlider = new SpinSlider("DEG OFFSET",0,360,(int)gauge.getDegreeOffset());
		degRangeSlider = new SpinSlider("DEG RANGE",0,360,(int)gauge.getDegreeRange());
		valueSlider = new SpinSlider("VALUE",0,(int)gauge.getMax(),(int)gauge.getValue());
		majorTickSlider = new SpinSlider("MAJOR",(int)gauge.getMin(),(int)gauge.getMax(),(int)gauge.getMajorTickSpacing());
		minorTickSlider = new SpinSlider("MINOR",0,majorTickSlider.getValue(),(int)gauge.getMinorTickSpacing());
		minorTickSlider.setMajorTickSpacing(minorTickSlider.getMaximum()/10);
		minorTickSlider.setMinorTickSpacing(minorTickSlider.getMajorTickSpacing()/10);
		
		installSlider(lctpSlider, "lctpSlider", "LCTP", panel);
		installSlider(stpSlider, "stpSlider", "SZTP", panel);
		installSlider(uctpSlider, "uctpSlider", "UCTP", panel);
		installSlider(udtpSlider, "udtpSlider", "UDTP", panel);
		installSlider(minSlider, "minSlider", "Min", panel);
		installSlider(maxSlider, "maxSlider", "Max", panel);
		installSlider(degRangeSlider, "degRangeSlider", "Range", panel);
		installSlider(offsetSlider, "offsetSlider", "Offset", panel);
		installSlider(zoneWidthSlider, "zoneWidthSlider", "ZWidth", panel);
		installSlider(valueSlider, "valueSlider", "Value", panel);
		installSlider(minorTickSlider, "minorTickSlider", "Minor", panel);
		installSlider(majorTickSlider, "majorTickSlider", "Major", panel);
		gauge.addChangeListener(this);
		
		valueSlider.getSlider().addChangeListener(this);
		valueSlider.setSize(new Dimension(50,600));
		frame.pack();
		frame.setVisible(true);
	}
	public void start()
	{
		
	}
	private void installSlider(SpinSlider slider, String name, String title, JPanel panel)
	{
		if(slider != null)
		{
		JPanel subPanel = new JPanel();
		subPanel.setLayout(new BoxLayout(subPanel, BoxLayout.Y_AXIS));
		// SpinSlider extends JPanel, not component so can't receive listeners.
		// instead, add listeners to the slider or spinner it contains.
		slider.getSlider().addChangeListener(this);
		//slider.setName(name);
		subPanel.add(slider);		
		panel.add(subPanel);
		
		}
	}
	
	@Override
	public void stateChanged(ChangeEvent e) {
		frame.pack();
		panel.repaint();
		
		if(e.getSource() == gauge)
			refreshSliderValues();
		if(e.getSource() == valueSlider.getSlider())
			gauge.setValue(valueSlider.getValue());
		if(e.getSource() == zoneWidthSlider.getSlider());
			gauge.setZoneArcThickness(zoneWidthSlider.getValue());
		if(e.getSource() == lctpSlider.getSlider())
			gauge.setLowerCautionTripPoint(lctpSlider.getValue());
		if(e.getSource() == stpSlider.getSlider())
			gauge.setSafeTripPoint(stpSlider.getValue());
		if(e.getSource() == uctpSlider.getSlider())
			gauge.setUpperCautionTripPoint(uctpSlider.getValue());
		if(e.getSource() == udtpSlider.getSlider())
			gauge.setUpperDangerTripPoint(udtpSlider.getValue());
		if(e.getSource() == minSlider.getSlider())
			gauge.setMin(minSlider.getValue()); 
		if(e.getSource() == maxSlider.getSlider())
			gauge.setMax(maxSlider.getValue()); 
		if(e.getSource() == degRangeSlider.getSlider())
			gauge.setDegreeRange(degRangeSlider.getValue()); 
		if(e.getSource() == offsetSlider.getSlider())
			gauge.setDegreeOffset(offsetSlider.getValue()); 
		if(e.getSource() == majorTickSlider.getSlider())
		{
			gauge.setMajorTickSpacing(majorTickSlider.getValue());
			minorTickSlider.setMaximum((int)majorTickSlider.getValue());
			
			if((int)(minorTickSlider.getMaximum()/10) > 0)
			{
				minorTickSlider.setLabelTable(minorTickSlider.createStandardLabels((int)(minorTickSlider.getMaximum()/10)));
			}
			else
			minorTickSlider.setLabelTable(minorTickSlider.createStandardLabels(1));
			
			minorTickSlider.setMajorTickSpacing(minorTickSlider.getMaximum()/10);
			minorTickSlider.setMinorTickSpacing(minorTickSlider.getMajorTickSpacing()/10);
			
		}
		if(e.getSource() == minorTickSlider.getSlider())
			gauge.setMinorTickSpacing(minorTickSlider.getValue());

	}
	private void refreshSliderValues()
	{
		// update the slider values when themodel changes.
		// can also use this to update the spinner values;
		
		degRangeSlider.setValue((int)gauge.getDegreeRange());
		lctpSlider.setValue((int)gauge.getLowerCautionTripPoint());
		majorTickSlider.setValue((int) gauge.getMajorTickSpacing());
		maxSlider.setValue((int)gauge.getMax());
		minorTickSlider.setValue((int)gauge.getMinorTickSpacing());
		minSlider.setValue((int)gauge.getMin());
		offsetSlider.setValue((int)gauge.getDegreeOffset());
		stpSlider.setValue((int)gauge.getSafeTripPoint());
		uctpSlider.setValue((int)gauge.getUpperCautionTripPoint());
		udtpSlider.setValue((int)gauge.getUpperDangerTripPoint());

		valueSlider.setValue((int)gauge.getValue());
		refreshSliderRanges();
	}
	private void refreshSliderRanges()
	{
		
		lctpSlider.setMinimum((int)gauge.getMin());
		lctpSlider.setMaximum((int)gauge.getMax());
		majorTickSlider.setMaximum((int)gauge.getMax());
		minorTickSlider.setMaximum((int)gauge.getMajorTickSpacing());
		stpSlider.setMinimum((int)gauge.getMin());
		stpSlider.setMaximum((int)gauge.getMax());
		uctpSlider.setMinimum((int)gauge.getMin());
		uctpSlider.setMaximum((int)gauge.getMax());
		udtpSlider.setMinimum((int)gauge.getMin());
		udtpSlider.setMaximum((int)gauge.getMax());
	
		valueSlider.setMinimum((int)gauge.getMin());
		valueSlider.setMaximum((int)gauge.getMax());
	}

}
